package com.hmall.cart.listener;

import com.hmall.api.client.UserClient;
import com.hmall.cart.service.ICartService;
import com.hmall.cart.service.impl.CartServiceImpl;
import com.hmall.common.utils.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.index.qual.SameLen;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * @author xiaopeng
 * @version 1.0
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class OrderCreateListener {
    private final CartServiceImpl cartService;

    /**
     * 法一：使用Map封装的方式传递用户ID
     * <p>
     * 监听订单创建时，清空购物车
     */
/*    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "cart.clear.queue",durable = "true"),
            exchange = @Exchange(name = "trade.topic"),
            key = "order.create"
    ))*/
    public void listenerOrderClear(Map<String, Object> messageMap) {
        try {
            // 获取 userId 和 itemIds
            Object userIdObj = messageMap.get("userId");
            Object itemIdsObj = messageMap.get("itemIds");

            // 输出类型
            log.info("userId 类型: {}", userIdObj.getClass().getName());
            log.info("itemIds 类型: {}", itemIdsObj.getClass().getName());

            // 强制转换并处理
            // 将 userId 从 Integer 转换为 Long
            Long userId = null;
            if (userIdObj instanceof Integer) {
                userId = Long.valueOf((Integer) userIdObj);
            } else {
                userId = (Long) userIdObj; // 如果已经是 Long 类型，直接使用
            }

            Collection<Long> itemIds = (Collection<Long>) itemIdsObj;

            log.info("收到订单创建消息，清除购物车中商品，userId：{}，itemIds：{}", userId, itemIds);
            UserContext.setUser(userId);
            cartService.removeByItemIds(itemIds);
        } catch (Exception e) {
            log.error("消费订单消息失败", e);
        }
    }

    /**
     * 法二：使用请求头的方式接受传递用户ID
     * 监听订单创建时，清空购物车
     *
     * @param itemIds
     * @param message
     */
/*    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "cart.clear.queue",durable = "true"),
            exchange = @Exchange(name = "trade.topic",type = ExchangeTypes.TOPIC),
            key = "order.create"
    ))*/
    public void listenerOrderClear(Set<Long> itemIds, Message message) {
        try {
            Long userId = message.getMessageProperties().getHeader("userId");
            log.info("收到订单创建消息，清除购物车中商品，userId：{}，itemIds：{}", userId, itemIds);
            UserContext.setUser(userId);
            cartService.removeByItemIds(itemIds);
        } catch (Exception e) {
            log.error("消费订单消息失败", e);
        } finally {
            // 清除 UserContext 中的用户信息
            // 消息消费结束后，确保清理 `UserContext`，避免线程污染
            UserContext.removeUser();
        }
    }


    /**
     * 法三：使用静态代理的方式，MessageConverterProxy
     * 通过静态代理模式来增强 `Jackson2JsonMessageConverter` 的功能，
     * 从而在其核心方法 `toMessage` 和 `fromMessage` 上进行扩展。
     * 例如，可以增强它的功能，将 `userId` 自动注入到消息头中，
     * 或者从消息头中提取 `userId` 并存储到 `UserContext`。
     *
     * @param itemIds
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "cart.clear.queue", durable = "true"),
            exchange = @Exchange(name = "trade.topic",type = ExchangeTypes.TOPIC),
            key = "order.create"
    ))
    public void listenerOrderClear(Set<Long> itemIds) {
        try {
            // 静态代理MessageConverterProxy：
            // 1、增强逻辑：在消息头中注入 userId
            // 2、增强逻辑：从消息头中提取 userId 并注入到 UserContext

            // 可直接从 UserContext 中获取 userId
            Long userId = UserContext.getUser();
            log.info("收到订单创建消息，清除购物车中商品，userId：{}，itemIds：{}", userId, itemIds);
            UserContext.setUser(userId);
            cartService.removeByItemIds(itemIds);
        } catch (Exception e) {
            log.error("消费订单消息失败", e);
        } finally {
            // 清除 UserContext 中的用户信息
            // 消息消费结束后，确保清理 `UserContext`，避免线程污染=
            UserContext.removeUser();
        }
    }
}
